local famBagsOptions = LibStub('AceAddon-3.0'):NewAddon('famBagsOptions', 'AceEvent-3.0')
local famBags = LibStub('AceAddon-3.0'):GetAddon('famBags')

local L = famBags.L

famBagsOptions.Sections = {
   ['bags'] = L['Bags'],
}
famBagsOptions.AppearanceCopyFrom = {}
famBagsOptions.AppearanceCopyFrom_DB = {}
famBagsOptions.CurrentAppearanceCopyFrom = 1

-- :::::::::::: LOCALS ::::::::::::: -------------------------------------------------------------------------

local LSM = LibStub('LibSharedMedia-3.0', true)
LoadAddOn('AceGUI-3.0-SharedMediaWidgets')
local AceGUI = LibStub('AceGUI-3.0')

local bg_types = {
   L['Solid'],
   L['Vertical gradient'],
   L['Horizontal gradient'],
   L['Texture']
}
local text_flags = {
   ['OUTLINE'] = L['OutLine'],
   ['THICKOUTLINE'] = L['Thick outline'],
   ['MONOCHROME'] = L['Monochrome'],
   ['SHADOW'] = L['Shadow'],
}
local horizontal_align = {
   ['LEFT'] = L['Left'],
   ['RIGHT'] = L['Right'],
   ['CENTER'] = L['Center'],
}
local vertical_align = {
   ['TOP'] = L['Top'],
   ['BOTTOM'] = L['Bottom'],
   ['CENTER'] = L['Center'],
}
local limited_horizontal_align = {
   ['LEFT'] = L['Left'],
   ['RIGHT'] = L['Right'],
}
local limited_vertical_align = {
   ['TOP'] = L['Top'],
   ['BOTTOM'] = L['Bottom'],
}

local quality_glows = {
   ['none'] = L['None'],
   ['square'] = L['Square'],
   ['round1'] = L['Light Rounded'],
   ['round2'] = L['Heavy Rounded'],
   ['circle'] = L['Circle'],
}

local stratas = {
   ['BACKGROUND'] = L['BACKGROUND'],
   ['LOW'] = L['LOW'],
   ['MEDIUM'] = L['MEDIUM'],
   ['HIGH'] = L['HIGH'],
   ['DIALOG'] = L['DIALOG'],
   ['TOOLTIP'] = L['TOOLTIP'],
}

local preset_options = {
   L['Don\'t include default categories'],
   L['Include just default categories'],
   L['Include default categories and their visual style'],
}

local SECTION_ARGS
local SECTIONS_TYPES = {
   ['onebag'] = L['One Bag'],
   ['bags'] = L['Bags'],
   ['categories'] = L['Categories'],
}
local ORDERS
local CURRENT_ORDER
local ORDER_ARGS = {}


local function get_order_index(orderdb)
   for i,o in ipairs(famBags.db.profile.layout.order.customs) do
      if o == orderdb then return i end
   end
   return nil
end

local function add_order()
   local db = famBags.db.profile.layout.order
   local new_order = {
      order = CURRENT_ORDER,
      sorting = famBags.Orders[CURRENT_ORDER][1]
   }
   table.insert(db.customs, new_order)
   famBagsOptions:AddOrderOptions(new_order)
   LibStub('AceConfigRegistry-3.0'):NotifyChange('famBags')
end

local function move_order(orderdb, step)
   local db = famBags.db.profile.layout.order
   local index = get_order_index(orderdb)
   local index2 = index + step
   if index2 < 1 or index2 > #db.customs then
      return
   end
   local order = ((index2-1) * 6) + 1
   ORDER_ARGS[orderdb.order..'_order'].order = order
   ORDER_ARGS[orderdb.order..'_sorting'].order = order + 1
   ORDER_ARGS[orderdb.order..'_up'].order = order + 2
   ORDER_ARGS[orderdb.order..'_down'].order = order + 3
   ORDER_ARGS[orderdb.order..'_delete'].order = order + 4
   ORDER_ARGS[orderdb.order..'_sep'].order = order + 5
   local orderdb2name = db.customs[index2].order
   order = ((index-1) * 6) + 1
   ORDER_ARGS[orderdb2name..'_order'].order = order
   ORDER_ARGS[orderdb2name..'_sorting'].order = order + 1
   ORDER_ARGS[orderdb2name..'_up'].order = order + 2
   ORDER_ARGS[orderdb2name..'_down'].order = order + 3
   ORDER_ARGS[orderdb2name..'_delete'].order = order + 4
   ORDER_ARGS[orderdb2name..'_sep'].order = order + 5
   db.customs[index], db.customs[index2] = db.customs[index2], db.customs[index]
   LibStub('AceConfigRegistry-3.0'):NotifyChange('famBags')
end

local function delete_order(orderdb)
   local db = famBags.db.profile.layout.order
   local index = get_order_index(orderdb)
   local order = ((index-1) * 6) + 6
   ORDER_ARGS[orderdb.order..'_order'] = nil
   ORDER_ARGS[orderdb.order..'_sorting'] = nil
   ORDER_ARGS[orderdb.order..'_up'] = nil
   ORDER_ARGS[orderdb.order..'_down'] = nil
   ORDER_ARGS[orderdb.order..'_delete'] = nil
   ORDER_ARGS[orderdb.order..'_sep'] = nil
   for _,arg in pairs(ORDER_ARGS) do
      if arg.order > order then
         arg.order = arg.order - 6
      end
   end
   table.remove(db.customs, index)
   LibStub('AceConfigRegistry-3.0'):NotifyChange('famBags')
end

local function get_array_len(arr)
   local i = 0
   for _ in pairs(arr) do
      i = i + 1
   end
   return i
end

local function get_max_order(arr)
   local i = 0
   for _, opt in pairs(arr) do
      if opt and opt.order then
         i = max(i, opt.order)
      end
   end
   return i
end

local function copy_table(from, to)
   for k, v in pairs(from) do
      if type(v) == 'table' then
         to[k] = to[k] or {}
         copy_table(from[k], to[k])
      else
         to[k] = v
      end
   end
end

local function copy_data(from, to, c, s)
   to.categoriesV2 = c
   to.sections = s
   if s and s.bags then
      local bags_section = {
         bg = famBags:GetBGDefaults(),
         title = famBags:GetTitleDefaults(),
      }
      copy_table(s.bags, bags_section)
      to.sections.bags = bags_section
   end

   copy_table(from['bankwindow'], to['bankwindow'])
   copy_table(from['bagswindow'], to['bagswindow'])
   copy_table(from['money'], to['money'])
   copy_table(from['layout'], to['layout'])
   copy_table(from['mainwindow'], to['mainwindow'])
   copy_table(from['bank'], to['bank'])
end

-- :::::::::::: famBagsOptions ::::::::::::: -------------------------------------------------------------------------
function famBagsOptions:OnInitialize()
   self.db = famBags.db
   local acr = LibStub('AceConfigRegistry-3.0')
   acr:RegisterOptionsTable('famBags', self:GetGlobalOptions())
   acr:RegisterOptionsTable('famBags Main bags', self:GetMainWindowOptions())
   acr:RegisterOptionsTable('famBags Bank', self:GetBankOptions())
   acr:RegisterOptionsTable('famBags Money', self:GetMoneyOptions())
   acr:RegisterOptionsTable('famBags Blizzard bank', self:GetBankWindowOptions())
   acr:RegisterOptionsTable('famBags Bags slots', self:GetBagsWindowOptions())
   acr:RegisterOptionsTable('famBags Sections', self:GetSectionsOptions('bags'))
   acr:RegisterOptionsTable('famBags Categories', self:GetCategoriesOptions())
   acr:RegisterOptionsTable('famBags Presets', self:GetPresetsOptions())
   acr:RegisterOptionsTable('famBags Offline', self:GetOfflineOptions())
   acr:RegisterOptionsTable('famBags Profiles', LibStub("AceDBOptions-3.0"):GetOptionsTable(famBags.db))

   local acd = LibStub('AceConfigDialog-3.0')
   acd:AddToBlizOptions('famBags', 'famBags')
   acd:AddToBlizOptions('famBags Main bags', L['Main bags'], 'famBags')
   acd:AddToBlizOptions('famBags Bank', L['Bank'], 'famBags')
   acd:AddToBlizOptions('famBags Money', L['Money'], 'famBags')
   acd:AddToBlizOptions('famBags Blizzard bank', L['Blizzard bank'], 'famBags')
   acd:AddToBlizOptions('famBags Bags slots', L['Bag slots'], 'famBags')
   acd:AddToBlizOptions('famBags Sections', L['Sections']..': '..L['Bags'], 'famBags')
   acd:AddToBlizOptions('famBags Categories', L['Categories'], 'famBags')
   acd:AddToBlizOptions('famBags Presets', L['Presets'], 'famBags')
   acd:AddToBlizOptions('famBags Offline', L['Global']..': '..L['Offline content & Alts'], 'famBags')
   acd:AddToBlizOptions('famBags Profiles', L['Profiles'], 'famBags')

  famBags.db.RegisterCallback(self, "OnProfileChanged", "FullRefresh")
  famBags.db.RegisterCallback(self, "OnProfileCopied", "FullRefresh")
  famBags.db.RegisterCallback(self, "OnProfileReset", "FullRefresh")
end

function famBagsOptions:OnEnable()
   --self:RegisterEvent('PLAYER_ENTERING_WORLD')TOTO =
end

function famBagsOptions:FullRefresh(name, profile, profilename)
   if name then
      if name == 'OnProfileChanged' and profilename then
         print('|cffff0000famBags: |r Applying |cff55FF55'..profilename..'|r profile')
      else
         print('|cffff0000famBags: |r Applying |cff55FF55'..name..'|r preset')
      end
   end
   famBags:FullRefresh(true)
   SECTION_ARGS = nil
   famBagsOptions.Sections = {
      ['bags'] = L['Bags'],
   }
   local acr = LibStub('AceConfigRegistry-3.0')
   acr:RegisterOptionsTable('famBags', self:GetGlobalOptions())
   acr:RegisterOptionsTable('famBags Main bags', self:GetMainWindowOptions())
   acr:RegisterOptionsTable('famBags Bank', self:GetBankOptions())
   acr:RegisterOptionsTable('famBags Money', self:GetMoneyOptions())
   acr:RegisterOptionsTable('famBags Blizzard bank', self:GetBankWindowOptions())
   acr:RegisterOptionsTable('famBags Bags slots', self:GetBagsWindowOptions())
   acr:RegisterOptionsTable('famBags Sections', self:GetSectionsOptions('bags'))
   acr:RegisterOptionsTable('famBags Categories', self:GetCategoriesOptions())
end

function famBagsOptions:GetGlobalOptions()
   local db = self.db.profile.layout
   local function get_opt(info)
      local id = info[#info]
      local section = info[#info-1]
      return db[section][id]
   end
   local function set_opt(info, value)
      local id = info[#info]
      local section = info[#info-1]
      db[section][id] = value
      if section..id == 'generalsections' then
         famBags.EMPTIES_NEED_LAYOUT.bags = true
         famBags.EMPTIES_NEED_LAYOUT.bank = true
         famBags.Sections:LayoutBags('bags', db.general.sections, true)
         famBags.Sections:LayoutBags('bank', db.general.sections, true)
      elseif section == 'buttons' or section == 'empties' then
         famBags:LayoutEmptiesButtons('bags')
         famBags:LayoutEmptiesButtons('bank')
      end
      if section == 'actions' then
         famBags:CreateIntefaceButtons()
      elseif section..id ~= 'generalinfo' then
         famBags:LayoutBagsButtons()
      end
   end
   if not ORDERS then
      ORDERS = {}
      for n in pairs(famBags.Orders) do
         ORDERS[n] = L[n]
      end
   end
   if not next(ORDER_ARGS) then
      for _,o in ipairs(famBags.db.profile.layout.order.customs) do
         famBagsOptions:AddOrderOptions(o)
      end
   end
   local empties = {
      name = L['Empty Slots'],
      type = 'group',
      args = self:GetAppearanceOptions({
         (famBags.Sections.bags.empties) and famBags.Sections.bags.empties.bodyFrame or nil,
         (famBags.Sections.bank.empties) and famBags.Sections.bank.empties.bodyFrame or nil
      }, db.empties, L['Empty Slots'])
   }
   empties.args.hpadding = {
      type = 'range',
      name = L['Horizontal padding'],
      get = get_opt,
      set = set_opt,
      min = 0,
      max = 30,
      step = 0.1,
      bigStep = 0.1,
      isPercent = false,
      order = 1,
   }
   empties.args.vpadding = {
      type = 'range',
      name = L['Vertical padding'],
      get = get_opt,
      set = set_opt,
      min = 0,
      max = 30,
      step = 0.1,
      bigStep = 0.1,
      isPercent = false,
      order = 2,
   }
   empties.args.hpos = {
      type = 'select',
      name = L['Horizontal align'],
      get = get_opt,
      set = set_opt,
      values = function(info)
         return limited_horizontal_align
      end,
      order = 3,
   }
   empties.args.vpos = {
      type = 'select',
      name = L['Vertical align'],
      get = get_opt,
      set = set_opt,
      values = function(info)
         return limited_vertical_align
      end,
      order = 4,
   }
   empties.args.no_empty_text = {
      type = 'input',
      name = L['No empty slots available text'],
      get = get_opt,
      set = set_opt,
      order = 5
   }
   empties.args.no_empty_color = {
      type = 'color',
      name = L['Color'],
      hasAlpha = false,
      width = 'half',
      get = function(info)
         return unpack(get_opt(info))
      end,
      set = function(info, r, g, b)
         set_opt(info, {r, g, b})
      end,
      disabled = function(info)
         return false
      end,
      order = 6,
   }
   return {
      name = L['famBags'],
      type = 'group',
      args = {
         general = {
            name = L['Global layout'],
            type = 'group',
            args = {
               strata = {
                  type = 'select',
                  name = L['Bags & bank strata'],
                  get = get_opt,
                  set = function(info, value)
                     famBags.famBagsFrame:SetFrameStrata(value)
                     famBags.famBankFrame:SetFrameStrata(value)
                     set_opt(info, value)
                  end,
                  values = function(info)
                     return stratas
                  end,
                  order = 1,
               },
               sections = {
                  type = 'select',
                  name = L['Layout'],
                  get = get_opt,
                  set = set_opt,
                  values = function(info)
                     return SECTIONS_TYPES
                  end,
                  order = 2,
               },
               full_layout = {
                  type = 'toggle',
                  name = L['Always layout'],
                  desc = L['If disabled bags wont update layout on items loss.'],
                  get = get_opt,
                  set = set_opt,
                  order = 3,
               },
               update_time = {
                  type = 'range',
                  name = L['Update interval'],
                  desc = L['Indicates how often bags will update layout when item operations are happening. Small numbers can decrease performance on mass operations.'],
                  get = get_opt,
                  set = set_opt,
                  min = 0.3,
                  max = 2,
                  step = 0.1,
                  bigStep = 0.1,
                  isPercent = false,
                  order = 4,
               },
               show_keys = {
                  type = 'toggle',
                  name = L['Show keys'],
                  get = get_opt,
                  set = function(info, value)
                     db.general.show_keys = value
                     if (not value) and famBags.Buttons[KEYRING_CONTAINER] then
                        for _, b in ipairs(famBags.Buttons[KEYRING_CONTAINER]) do
                           b:Hide()
                        end
                     end
                     famBags:BuildBagIndexes()
                     famBags.EMPTIES_NEED_LAYOUT['bags'] = true
                     set_opt(info, value)
                  end,
                  order = 5,
               },
               info = {
                  type = 'toggle',
                  name = L['Show items info in tooltip'],
                  get = get_opt,
                  set = set_opt,
                  order = 6,
               },
            },
            order = 1,
         },
         sections = {
            name = L['Sections layout'],
            type = 'group',
            args = {
               compact = {
                  type = 'toggle',
                  name = L['Compact layout'],
                  get = get_opt,
                  set = set_opt,
                  order = 1,
               },
               h = {
                  type = 'header',
                  name = '',
                  order = 2,
               },
               hpadding = {
                  type = 'range',
                  name = L['Horizontal padding'],
                  get = get_opt,
                  set = set_opt,
                  min = 0,
                  max = 30,
                  step = 0.1,
                  bigStep = 0.1,
                  isPercent = false,
                  order = 3,
               },
               vpadding = {
                  type = 'range',
                  name = L['Vertical padding'],
                  get = get_opt,
                  set = set_opt,
                  min = 0,
                  max = 30,
                  step = 0.1,
                  bigStep = 0.1,
                  isPercent = false,
                  order = 4,
               },
               hspacing = {
                  type = 'range',
                  name = L['Horizontal spacing'],
                  get = get_opt,
                  set = set_opt,
                  min = 0,
                  max = 30,
                  step = 0.1,
                  bigStep = 0.1,
                  isPercent = false,
                  order = 5,
               },
               vspacing = {
                  type = 'range',
                  name = L['Vertical spacing'],
                  get = get_opt,
                  set = set_opt,
                  min = 0,
                  max = 30,
                  step = 0.1,
                  bigStep = 0.1,
                  isPercent = false,
                  order = 6,
               },
               h1 = {
                  type = 'header',
                  name = '',
                  order = 7,
               },
               tooltip = {
                  type = 'toggle',
                  name = L['Show tooltip'],
                  get = get_opt,
                  set = set_opt,
                  order = 8,
               },
               break1 = {
                  type = 'description',
                  name = '',
                  hidden = function() return not db.sections.tooltip end,
                  order = 9,
               },
               tooltip_vendor = {
                  type = 'toggle',
                  name = L['Vendor Value'],
                  get = get_opt,
                  set = set_opt,
                  hidden = function() return not db.sections.tooltip end,
                  order = 10,
               },
               h2 = {
                  type = 'header',
                  name = '',
                  order = 11,
               },
            },
            order = 2,
         },
         stacks = {
            name = L['Stacks'],
            type = 'group',
            args = {
               only_stackable = {
                  type = 'toggle',
                  name = L['Only stackable items'],
                  get = get_opt,
                  set = set_opt,
                  order = 1,
               },
               only_full = {
                  type = 'toggle',
                  name = L['Only full stacks'],
                  get = get_opt,
                  set = set_opt,
                  order = 2,
               },
            },
            order = 3,
         },
         buttons = {
            name = L['Items layout'],
            type = 'group',
            args = {
               hpadding = {
                  type = 'range',
                  name = L['Horizontal padding'],
                  get = get_opt,
                  set = set_opt,
                  min = 0,
                  max = 30,
                  step = 0.1,
                  bigStep = 0.1,
                  isPercent = false,
                  order = 1,
               },
               vpadding = {
                  type = 'range',
                  name = L['Vertical padding'],
                  get = get_opt,
                  set = set_opt,
                  min = 0,
                  max = 30,
                  step = 0.1,
                  bigStep = 0.1,
                  isPercent = false,
                  order = 2,
               },
               hspacing = {
                  type = 'range',
                  name = L['Horizontal spacing'],
                  get = get_opt,
                  set = set_opt,
                  min = 0,
                  max = 30,
                  step = 0.1,
                  bigStep = 0.1,
                  isPercent = false,
                  order = 3,
               },
               vspacing = {
                  type = 'range',
                  name = L['Vertical spacing'],
                  get = get_opt,
                  set = set_opt,
                  min = 0,
                  max = 30,
                  step = 0.1,
                  bigStep = 0.1,
                  isPercent = false,
                  order = 4,
               },
               h2 = {
                  type = 'header',
                  name = '',
                  order = 5,
               },
               size = {
                  type = 'range',
                  name = L['Size'],
                  get = get_opt,
                  set = function(info, value)
                     set_opt(info, value)
                     famBags.Buttons:UpdateButtonsScale()
                  end,
                  min = 0.1,
                  max = 2,
                  step = 0.05,
                  bigStep = 0.05,
                  isPercent = true,
                  order = 6,
               },
               quality_glow = {
                  type = 'select',
                  name = L['Quality glow'],
                  get = get_opt,
                  set = function(info, value)
                     set_opt(info, value)
                     famBags.Buttons:UpdateAllButtonsQuality()
                  end,
                  values = function(info)
                     return quality_glows
                  end,
                  order = 7,
               },
               quality_glow_alpha = {
                  type = 'range',
                  name = L['Quality glow intensity'],
                  get = get_opt,
                  set = function(info, value)
                     set_opt(info, value)
                     famBags.Buttons:UpdateAllButtonsQuality()
                  end,
                  min = 0,
                  max = 1,
                  step = 0.05,
                  bigStep = 0.05,
                  isPercent = true,
                  hidden = function() return db.buttons.quality_glow == 'none' end,
                  order = 8,
               },
               quality_glow_inset = {
                  type = 'range',
                  name = L['Quality glow inset'],
                  get = get_opt,
                  set = function(info, value)
                     set_opt(info, value)
                     famBags.Buttons:UpdateAllButtonsQuality()
                  end,
                  min = -10,
                  max = 10,
                  step = 1,
                  bigStep = 1,
                  isPercent = false,
                  hidden = function() return db.buttons.quality_glow == 'none' end,
                  order = 9,
               },
               h3 = {
                  type = 'header',
                  name = '',
                  order = 10,
               },
               indicators_enabled = {
                  type = 'toggle',
                  name = L['Enable indicators'],
                  get = get_opt,
                  set = function(info, value)
                     db.buttons.indicators_enabled = value
                     famBags.Buttons:UpdateAllIndicators()
                     famBags:LayoutBagsButtons()
                  end,
                  order = 11,
               },
               indicators_size = {
                  type = 'range',
                  name = L['Indicators size'],
                  get = get_opt,
                  set = function(info, value)
                     db.buttons.indicators_size = value
                     famBags.Buttons:UpdateAllIndicators()
                     famBags:LayoutBagsButtons()
                  end,
                  min = 0.1,
                  max = 2,
                  step = 0.01,
                  bigStep = 0.01,
                  isPercent = true,
                  hidden = function() return not db.buttons.indicators_enabled end,
                  order = 12,
               },
               indicators_offset = {
                  type = 'range',
                  name = L['Indicators offset'],
                  get = get_opt,
                  set = function(info, value)
                     db.buttons.indicators_offset = value
                     famBags.Buttons:UpdateAllIndicators()
                     famBags:LayoutBagsButtons()
                  end,
                  min = -10,
                  max = 10,
                  step = 1,
                  bigStep = 1,
                  isPercent = false,
                  hidden = function() return not db.buttons.indicators_enabled end,
                  order = 13,
               },
            },
            order = 4,
         },
         counts = self:GetTextOptions(nil, nil, db.counts, false, true, false),
         empties = empties,
         order = {
            name = L['Items Order'],
            type = 'group',
            args = {
               ordered = {
                  type = 'toggle',
                  name = L['Order items'],
                  get = get_opt,
                  set = set_opt,
                  order = 1,
               },
               default = {
                  type = 'toggle',
                  name = L['Default Order (faster)'],
                  get = get_opt,
                  set = set_opt,
                  order = 2,
                  disabled = function() return not db.order.ordered end,
               },
               h1 = {
                  type = 'header',
                  name = '',
                  order = 3,
               },
               orders = {
                  type = 'select',
                  name = L['Order Criteria'],
                  get = function(info,key)
                     if not rawget(ORDERS, CURRENT_ORDER) then
                        CURRENT_ORDER = next(ORDERS)
                     end
                     return CURRENT_ORDER
                  end,
                  set = function(info, value)
                     CURRENT_ORDER = value
                  end,
                  values = function(info)
                     return ORDERS
                  end,
                  disabled = function() return not db.order.ordered or db.order.default end,
                  order = 4,
               },
               add_order = {
                  type = 'execute',
                  name = L['Add'],
                  width = 'half',
                  func = function(info)
                     add_order()
                     famBags:LayoutBagsButtons()
                  end,
                  disabled = function()
                     if not db.order.ordered or db.order.default then return true end
                     for _,o in ipairs(famBags.db.profile.layout.order.customs) do
                        if o.order == CURRENT_ORDER then return true end
                     end
                     return nil
                  end,
                  order = 5,
               },
               orders_list = {
                  name = L['Items Order'],
                  type = 'group',
                  inline = true,
                  args = ORDER_ARGS,
                  disabled = function() return not db.order.ordered or db.order.default end,
                  order = 6,
               }
            },
         },
         actions = {
            name = L['Action buttons'],
            type = 'group',
            args = {
               stack = {
                  type = 'toggle',
                  name = '|TInterface\\Addons\\famBags\\Textures\\btnstack.blp:50:50:0:0:64:64:0:64:0:64|t',
                  desc = L['Stacking mode on/off'],
                  width = 'half',
                  get = get_opt,
                  set = set_opt,
                  order = 1,
               },
               refresh = {
                  type = 'toggle',
                  name = '|TInterface\\Addons\\famBags\\Textures\\btnrefresh.blp:50:50:0:0:64:64:0:64:0:64|t',
                  desc = L['Refresh Layout'],
                  width = 'half',
                  get = get_opt,
                  set = set_opt,
                  order = 2,
               },
               bagswindow = {
                  type = 'toggle',
                  name = '|TInterface\\Addons\\famBags\\Textures\\btnshowbags.blp:50:50:0:0:64:64:0:64:0:64|t',
                  desc = L['Bag slots on/off'],
                  width = 'half',
                  get = get_opt,
                  set = set_opt,
                  order = 3,
               },
               resetupdated = {
                  type = 'toggle',
                  name = '|TInterface\\Addons\\famBags\\Textures\\btnreset.blp:50:50:0:0:64:64:0:64:0:64|t',
                  desc = L['Reset updated item indicators'],
                  width = 'half',
                  get = get_opt,
                  set = set_opt,
                  order = 4,
               },
               search = {
                  type = 'toggle',
                  name = '|TInterface\\Addons\\famBags\\Textures\\btnsearch.blp:50:50:0:0:64:64:0:64:0:64|t',
                  desc = L['Search mode on/off'],
                  width = 'half',
                  get = get_opt,
                  set = set_opt,
                  order = 5,
               },
               optimize = {
                  type = 'toggle',
                  name = '|TInterface\\Addons\\famBags\\Textures\\btnrestack.blp:50:50:0:0:64:64:0:64:0:64|t',
                  desc = L['Optimize stacks'],
                  width = 'half',
                  get = get_opt,
                  set = set_opt,
                  order = 6,
               },
               options = {
                  type = 'toggle',
                  name = '|TInterface\\Addons\\famBags\\Textures\\btnoptions.blp:50:50:0:0:64:64:0:64:0:64|t',
                  desc = L['Options'],
                  width = 'half',
                  get = get_opt,
                  set = set_opt,
                  order = 7,
               },
               alts = {
                  type = 'toggle',
                  name = '|TInterface\\Addons\\famBags\\Textures\\btnalts.blp:50:50:0:0:64:64:0:64:0:64|t',
                  desc = L['Options'],
                  width = 'half',
                  get = get_opt,
                  set = set_opt,
                  order = 8,
               },
            },
         },
      },
   }
end

function famBagsOptions:GetWindowLayoutOptions(frame, db)
   local function get_opt(info)
      local id = info[#info]
      return db[id]
   end
   local function set_opt(info, value)
      local id = info[#info]
      db[id] = value
      if id == 'buttons_x_row' or id == 'fixed_width' then
         famBags:LayoutBagsButtons()
      else
         famBags:PositionBagFromDB(frame, UIParent, db)
      end
   end
   return {
      buttons_x_row = {
         type = 'range',
         name = L['Max buttons x row'],
         get = get_opt,
         set = set_opt,
         min = 6,
         max = 30,
         step = 1,
         bigStep = 1,
         isPercent = false,
         order = 1,
      },
      fixed_width = {
         type = 'toggle',
         name = L['Fixed width'],
         get = get_opt,
         set = set_opt,
         order = 2,
      },
      halign = {
         type = 'select',
         name = L['Horizontal align'],
         get = get_opt,
         set = set_opt,
         values = function(info)
            return horizontal_align
         end,
         order = 3,
      },
      valign = {
         type = 'select',
         name = L['Vertical align'],
         get = get_opt,
         set = set_opt,
         values = function(info)
            return vertical_align
         end,
         order = 4,
      },
      hspacing = {
         type = 'range',
         name = L['Horizontal spacing'],
         get = get_opt,
         set = set_opt,
         min = 0,
         max = 1000,
         step = 10,
         bigStep = 10,
         isPercent = false,
         order = 5,
      },
      vspacing = {
         type = 'range',
         name = L['Vertical spacing'],
         get = get_opt,
         set = set_opt,
         min = 0,
         max = 1000,
         step = 10,
         bigStep = 1,
         isPercent = false,
         order = 6,
      },
      persist_pos = {
         type = 'toggle',
         name = L['Persistent position'],
         get = get_opt,
         set = set_opt,
         order = 7,
      },
   }
end

function famBagsOptions:GetMainWindowOptions()
   return {
      name = L['Main bags'],
      desc = L['Main bags options'],
      type = 'group',
      args = {
         layout = {
            name = L['Layout'],
            type = 'group',
            args =  self:GetWindowLayoutOptions(famBags.famBagsFrame, self.db.profile.mainwindow.layout),
            order = 1,
         },
         appearance = {
            name = L['Appearance'],
            type = 'group',
            args =  self:GetAppearanceOptions({famBags.famBagsFrame.bodyFrame}, self.db.profile.mainwindow, L['Main bags']),
            order = 2,
         },
         title = {
            name = L['Title'],
            type = 'group',
            args =  self:GetTitleOptions({famBags.famBagsFrame}, self.db.profile.mainwindow, true, L['Main bags']..' -> '..L['Title']),
            order = 3,
         },
         search = {
            name = L['Search'],
            type = 'group',
            args =  self:GetSearchOptions(famBags.BagsSearchFrame, self.db.profile.mainwindow.search, L['Main bags']..' -> '..L['Search']),
            order = 4,
         },
         alts = {
            name = L['Alts'],
            type = 'group',
            args =  self:GetSearchOptions(famBags.BagsAltsFrame, self.db.profile.mainwindow.alts, L['Main bags']..' -> '..L['Alts']),
            order = 5,
            hidden = function() return not famBags.OFFLINE_ENABLED end,
         },
      },
   }
end

function famBagsOptions:GetMoneyOptions()
   local db = self.db.profile.money
   local function get_opt(info)
      local id = info[#info]
      return db[id]
   end
   local function set_opt(info, value)
      local id = info[#info]
      db[id] = value
      famBags:UpdateMoneyFrame()
      famBags:UpdateCurrency()
   end
   local args = self:GetAppearanceOptions({famBags.famBagsMoneyFrame}, db, L['Money'])
   args['text'] = self:GetTextOptions({famBags.famBagsMoneyFrame}, 'moneyText', db.text, false, false, true)
   args['main'] = {
      name = L['General'],
      type = 'group',
      inline = true,
      args = {
         enabled = {
            type = 'toggle',
            name = L['Enabled'],
            get = get_opt,
            set = set_opt,
            order = 1,
         },
         show_silver = {
            type = 'toggle',
            name = '|TInterface\\MoneyFrame\\UI-SilverIcon:16:16:3:0:64:64:4:60:4:60|t ',
            desc = L['Show silver'],
            width = 'half',
            get = get_opt,
            set = set_opt,
            order = 2,
         },
         show_copper = {
            type = 'toggle',
            name = '|TInterface\\MoneyFrame\\UI-CopperIcon:16:16:3:0:64:64:4:60:4:60|t ',
            desc = L['Show copper'],
            width = 'half',
            get = get_opt,
            set = set_opt,
            order = 3,
         },
      },
      order = 1,
   }
   return {
      name = L['Money'],
      desc = L['Money options'],
      type = 'group',
      args = args,
   }
end

function famBagsOptions:GetBankWindowOptions()
   local db = self.db.profile.bankwindow
   local function get_opt(info)
      local id = info[#info]
      return db[id]
   end
   local function set_opt(info, value)
      local id = info[#info]
      db[id] = value
   end
   local args = self:GetAppearanceOptions({famBags.famBagsBlizzardBankFrame}, db, L['Blizzard bank'])
   args['main'] = {
      name = L['General'],
      type = 'group',
      inline = true,
      args = {
         enabled = {
            type = 'toggle',
            name = L['Override bank. Requires Restart.'],
            name = L['Override Blizzard bank main window. Requires restart.'],
            width = 'full',
            get = get_opt,
            set = set_opt,
            order = 1,
         },
      },
      order = 1,
   }
   return {
      name = L['Blizzard bank'],
      desc = L['Blizzard bank window override options'],
      type = 'group',
      args = args,
   }
end

function famBagsOptions:GetBagsWindowOptions()
   local db = self.db.profile.bagswindow
   local function get_opt(info)
      local id = info[#info]
      return db[id]
   end
   local function set_opt(info, value)
      local id = info[#info]
      db[id] = value
   end
   local args = self:GetAppearanceOptions({famBags.famBagsBagSlotsFrame}, db, L['Bag slots'])
   args['main'] = {
      name = L['General'],
      type = 'group',
      inline = true,
      args = {
         enabled = {
            type = 'toggle',
            name = L['Collect default bag slots. Requires restart.'],
            name = L['Collect Blizzard default bag slots from UI. Requires restart.'],
            width = 'full',
            get = get_opt,
            set = set_opt,
            order = 1,
         },
      },
      order = 1,
   }
   return {
      name = L['Bag slots'],
      desc = L['Bag slots options'],
      type = 'group',
      args = args,
   }
end

function famBagsOptions:GetBankOptions()
   return {
      name = L['Bank'],
      desc = L['Bank options'],
      type = 'group',
      args = {
         layout = {
            name = L['Layout'],
            type = 'group',
            args =  self:GetWindowLayoutOptions(famBags.famBankFrame, self.db.profile.bank.layout),
            order = 1,
         },
         appearance = {
            name = L['Appearance'],
            type = 'group',
            args =  self:GetAppearanceOptions({famBags.famBankFrame.bodyFrame}, self.db.profile.bank, L['Bank']),
            order = 2,
         },
         title = {
            name = L['Title'],
            type = 'group',
            args =  self:GetTitleOptions({famBags.famBankFrame}, self.db.profile.bank, true, L['Bank']..' -> '..L['Title']),
            order = 3,
         },
         search = {
            name = L['Search'],
            type = 'group',
            args =  self:GetSearchOptions(famBags.BankSearchFrame, self.db.profile.bank.search, L['Bank']..' -> '..L['Search']),
            order = 4,
         },
         alts = {
            name = L['Alts'],
            type = 'group',
            args =  self:GetSearchOptions(famBags.BankAltsFrame, self.db.profile.bank.alts, L['Bank']..' -> '..L['Alts']),
            order = 5,
            hidden = function() return not famBags.OFFLINE_ENABLED end,
         },
      },
   }
end

function famBagsOptions:GetPresetsOptions()
   local current_preset
   local preset_option = 1
   return {
      name = L['Presets'],
      desc = L['Presets options'],
      type = 'group',
      args = {
         presets = {
            type = 'select',
            name = L['Presets'],
            get = function(info,key)
               if not famBags.PresetNames[current_preset] then
                  current_preset = 1
               end
               return current_preset
            end,
            set = function(info, value)
               current_preset = value
            end,
            values = function(info)
               return famBags.PresetNames
            end,
            order = 1,
         },
         preset_opt = {
            type = 'select',
            name = ' ',
            width = 'double',
            get = function(info,key)
               if not preset_option then
                  preset_option = 1
               end
               return preset_option
            end,
            set = function(info, value)
               preset_option = value
            end,
            values = function(info)
               return preset_options
            end,
            order = 2,
         },
         apply = {
            type = 'execute',
            name = L['Apply preset'],
            func = function(info)
               self:ApplyPreset(current_preset, preset_option)
            end,
            order = 3,
         }
      },
   }
end

function famBagsOptions:GetOfflineOptions()
   local db = self.db.global.offline
   local function get_opt(info)
      local id = info[#info]
      return db[id]
   end
   local function set_opt(info, value)
      local id = info[#info]
      db[id] = value
   end
   return {
      name = L['Offline content & Alts'],
      type = 'group',
      args = {
         enabled = {
            type = 'toggle',
            name = L['Enabled'],
            get = get_opt,
            set = set_opt,
            width = 'full',
            order = 1,
         },
         desc = {
            type = 'description',
            name = '|cfff3cc20'..L['OFFLINE_ENABLE_DESC'],
            fontSize = 'small',
            order = 2,
         },
      },
   }
end

function famBagsOptions:ApplyPreset(current_preset, preset_option)
   local c = (preset_option == 1) and famBags.db.profile.categoriesV2 or CopyTable(famBags.DefaultCategories)
   local s = (preset_option < 3) and famBags.db.profile.sections or CopyTable(famBags.Presets[current_preset].sections)
   wipe(famBags.db.profile)
   local defaults = famBags:GetDBDefaults().profile
   for k, t in pairs(defaults) do
      famBags.db.profile[k] = (type(t) == 'table') and CopyTable(t) or t
   end
   copy_data(famBags.Presets[current_preset], famBags.db.profile, c, s)
   self:FullRefresh(famBags.PresetNames[current_preset])
   ReloadUI()
end

function famBagsOptions:GetSectionsOptions(section, refreshCallback)
   local copy_from
   local dbs = famBags.db.profile.sections
   local function get_sections_frames(frameIndex)
      frames = {}
      local sections_type = self.db.profile.layout.general.sections
      for bag in pairs(famBags.BagIndexes) do
         local s = sections_type == 'bags' and famBags.Sections[bag] or famBags.Sections[bag].categories
         if s and s[section] then
            if sections_type == 'bags' then
               for _, sections in pairs(s[section]) do
                  if frameIndex and sections[frameIndex] then
                     table.insert(frames, sections[frameIndex])
                  else
                     table.insert(frames, sections)
                  end
               end
            elseif sections_type == 'categories' then
               if s[section] then
                  if frameIndex and s[section][frameIndex] then
                     table.insert(frames, s[section][frameIndex])
                  else
                     table.insert(frames, s[section])
                  end
               end
            end
         end
      end
      return frames
   end
   SECTION_ARGS = {
      copy_from = {
         type = 'select',
         name = L['Copy from'],
         get = function(info,key)
            if not rawget(famBagsOptions.Sections, copy_from) then
               copy_from = next(famBagsOptions.Sections)
            end
            return copy_from
         end,
         set = function(info, value)
            copy_from = value
         end,
         values = function(info)
            return famBagsOptions.Sections
         end,
         order = 1,
      },
      copy = {
         type = 'execute',
         name = L['Copy'],
         width = 'half',
         func = function(info)
            if not famBags.db.profile.sections[copy_from] then return end
            famBags.db.profile.sections[section] = CopyTable(famBags.db.profile.sections[copy_from])
            local frames = get_sections_frames('bodyFrame')
            for _, frame in ipairs(frames) do
               if (frame) then
                  local parent = frame:GetParent()
                  famBags:SetFrameBackdrop(frame, dbs[section])
                  famBags:SetFrameBackdrop(parent.titleFrame, dbs[section].title)
                  famBags:SetTitleInset(parent, dbs[section].title.is_inset, dbs[section].title.inset, dbs[section].title.text.padding)
                  famBags:SetTextLayout(parent.titleFrame, 'titleText', dbs[section].title.text, nil)
               end
            end
            famBags:LayoutBagsButtons()
            if section == 'bags' then
               LibStub('AceConfigRegistry-3.0'):NotifyChange('famBags Sections')
            elseif refreshCallback then
               refreshCallback(famBagsOptions.Categories, section, true)
            end
         end,
         disabled = function()
            return section == copy_from
         end,
         order = 2,
      },
      h2 = {
         type = 'header',
         name = '',
         order = 3,
      },
      appearance = {
         name = L['Appearance'],
         type = 'group',
         args =  self:GetAppearanceOptions(get_sections_frames('bodyFrame'), dbs[section], L['Sections']..' -> '..section)
      },
      title = {
         name = L['Title'],
         type = 'group',
         args =  self:GetTitleOptions(get_sections_frames(), dbs[section], true, L['Sections']..' -> '..section..' -> '..L['Title'])
      }
   }

   return {
      name = '',
      desc = L['Sections options'],
      type = 'group',
      args = SECTION_ARGS
   }
end

function famBagsOptions:GetSearchOptions(frame, db, name)
   local function get_opt(info)
      local id = info[#info]
      return db[id]
   end
   local function set_opt(info, value)
      local id = info[#info]
      db[id] = value
      famBags:UpdateInputFrame(frame, db)
   end
   local args = self:GetAppearanceOptions({frame}, db, name)
   args['general'] = {
      name = L['General'],
      type = 'group',
      inline = true,
      args = {
         hpadding = {
            type = 'range',
            name = L['Horizontal padding'],
            get = get_opt,
            set = set_opt,
            min = -30,
            max = 30,
            step = 0.1,
            bigStep = 0.1,
            isPercent = false,
            order = 1,
         },
         vpadding = {
            type = 'range',
            name = L['Vertical padding'],
            get = get_opt,
            set = set_opt,
            min = -30,
            max = 30,
            step = 0.1,
            bigStep = 0.1,
            isPercent = false,
            order = 2,
         },
         width = {
            type = 'range',
            name = L['Size'],
            get = get_opt,
            set = set_opt,
            min = 0.2,
            max = 1,
            step = 0.01,
            bigStep = 0.01,
            isPercent = true,
            order = 3,
         },
         level = {
            type = 'range',
            name = L['Level'],
            get = get_opt,
            set = set_opt,
            min = 0,
            max = 20,
            step = 0.1,
            bigStep = 0.1,
            isPercent = false,
            order = 4,
         },
         animation = {
            type = 'toggle',
            name = L['Animation'],
            get = get_opt,
            set = set_opt,
            order = 5,
         },
      },
      order = 1,
   }
   return args
end

function famBagsOptions:GetAppearanceOptions(frames, db, name)
   if not tContains(self.AppearanceCopyFrom, name) then
      table.insert(self.AppearanceCopyFrom, name)
      self.AppearanceCopyFrom_DB[name] = db.bg
      table.sort(self.AppearanceCopyFrom)
   end
   if not db.bg.color2 then
      db.bg.color2 = {0,0,0,0.7}
   end
   if not db.bg.br_color then
      db.bg.br_color = {0,0,0,0.7}
   end
   local function update_frames()
      if frames then
         for _, frame in ipairs(frames) do
            if (frame) then
               famBags:SetFrameBackdrop(frame, db)
            end
         end
      end
   end
   local function get_opt(info)
      local id = info[#info]
      return db.bg[id]
   end
   local function set_opt(info, value)
      local id = info[#info]
      db.bg[id] = value
      update_frames()
   end
   return {
      bg = {
         name = L['Appearance'],
         type = 'group',
         inline = true,
         args = {
            copy_from = {
               type = 'select',
               dialogControl = 'Dropdown',
               name = L['Copy from'],
               width = 'double',
               get = function(info, key)
                  return self.CurrentAppearanceCopyFrom
               end,
               set = function(info, key, value)
                  self.CurrentAppearanceCopyFrom = key
               end,
               values = function(info)
                  return self.AppearanceCopyFrom
               end,
               order = 1,
            },
            copy = {
               type = 'execute',
               name = L['Copy'],
               width = 'half',
               func = function(info)
                  if self.CurrentAppearanceCopyFrom and self.AppearanceCopyFrom[self.CurrentAppearanceCopyFrom] and
                     self.AppearanceCopyFrom_DB[self.AppearanceCopyFrom[self.CurrentAppearanceCopyFrom]] then
                     copy_table(self.AppearanceCopyFrom_DB[self.AppearanceCopyFrom[self.CurrentAppearanceCopyFrom]], db.bg)
                     update_frames()
                  end
               end,
               disabled = function()
                  return false
               end,
               order = 2,
            },
            h1 = {
               name = L['Background'],
               type = 'header',
               order = 3,
            },
            type = {
               type = 'select',
               dialogControl = MULTISELECT_CONTROL,
               name = L['Type'],
               get = get_opt,
               set = set_opt,
               values = function(info)
                  return bg_types
               end,
               order = 4,
            },
            h2 = {
               type = 'header',
               name = '',
               order = 5,
            },
            texture = {
               type = 'select',
               dialogControl = AceGUI.WidgetRegistry['LSM30_Background'] and 'LSM30_Background' or nil,
               name = L['Texture'],
               get = get_opt,
               set = set_opt,
               values = function(info)
                  return LSM:HashTable('background')
               end,
               order = 6,
               hidden = function(info)
                  return db.bg.type ~= 4 --[[ Texture--]]
               end,
            },
            color1 = {
               type = 'color',
               width = 'half',
               name = function()
                  if db.bg.type == 1 --[[ Solid--]] then
                     return L['Color']
                  else
                     return L['Start color']
                  end
               end,
               hasAlpha = true,
               get = function(info)
                  return unpack(get_opt(info))
               end,
               set = function(info, r, g, b, a)
                  set_opt(info, {r, g, b, a})
               end,
               disabled = function(info)
                  return false
               end,
               order = 7,
            },
            color2 = {
               type = 'color',
               name = L['End color'],
               hasAlpha = true,
               width = 'half',
               get = function(info)
                  return unpack(get_opt(info))
               end,
               set = function(info, r, g, b, a)
                  set_opt(info, {r, g, b, a})
               end,
               disabled = function(info)
                  return false
               end,
               hidden = function(info)
                  return db.bg.type == 1 --[[ Solid--]] or db.bg.type == 4 --[[ Texture--]]
               end,
               order = 8,
            },
            inset = {
               type = 'range',
               name = L['Inset'],
               get = get_opt,
               set = set_opt,
               min = -50,
               max = 50,
               step = 1,
               bigStep = 1,
               isPercent = false,
               order = 9,
            },
            h2 = {
               name = L['Border'],
               type = 'header',
               order = 10,
            },
            br_texture = {
               type = 'select',
               dialogControl = AceGUI.WidgetRegistry['LSM30_Border'] and 'LSM30_Border' or nil,
               name = L['Texture'],
               get = get_opt,
               set = set_opt,
               values = function(info)
                  return LSM:HashTable('border')
               end,
               order = 11,
            },
            br_color = {
               type = 'color',
               name = L['Color'],
               hasAlpha = true,
               width = 'half',
               get = function(info)
                  return unpack(get_opt(info))
               end,
               set = function(info, r, g, b, a)
                  set_opt(info, {r, g, b, a})
               end,
               disabled = function(info)
                  return db.bg.br_texture == 'None'
               end,
               order = 12,
            },
            br_size = {
               type = 'range',
               name = L['Edge size'],
               get = get_opt,
               set = set_opt,
               min = 0,
               max = 50,
               step = 1,
               bigStep = 1,
               isPercent = false,
               disabled = function(info)
                  return db.bg.br_texture == 'None'
               end,
               order = 13,
            },
         }
      },
   }
end

function famBagsOptions:GetTextOptions(frames, name, db, refreshLayout, counts, inline)
   local function get_opt(info)
      local id = info[#info]
      return db[id]
   end
   local function set_opt(info, value)
      local id = info[#info]
      db[id] = value
      if counts then
         for _, indexes in pairs(famBags.BagIndexes) do
            for _, i in ipairs(indexes) do
               if famBags.Buttons[i] then
                  for _, b in ipairs(famBags.Buttons[i]) do
                     famBags:SetTextLayout(b, _G[b:GetName().."Count"], db, nil)
                  end
               end
            end
         end
      elseif frames then
         for _, frame in ipairs(frames) do
            if frame then
               famBags:SetTextLayout(frame, name, db, nil)
            end
         end
      end
      if refreshLayout then
         famBags:LayoutBagsButtons()
      end
   end
   return {
      name = (counts) and L['Counts'] or L['Text'],
      type = 'group',
      inline = inline,
      args = {
         font = {
            type = 'select',
            dialogControl = AceGUI.WidgetRegistry['LSM30_Font'] and 'LSM30_Font' or nil,
            name = L['Font'],
            get = get_opt,
            set = set_opt,
            values = function(info)
               return LSM:HashTable('font')
            end,
            order = 1,
         },
         flags = {
            type = 'multiselect',
            name = L['Flags'],
            dialogControl = 'Dropdown',
            get = function(info, key)
               return (db and db.flags and db.flags[key]) and db.flags[key] or nil
            end,
            set = function(info, key, value)
               db.flags[key] = value
               if frames then
                  for _, frame in ipairs(frames) do
                     if frame then
                        famBags:SetTextLayout(frame, name, db)
                     end
                  end
               end
            end,
            values = function(info)
               return text_flags
            end,
            order = 2,
         },
         size = {
            type = 'range',
            name = L['Size'],
            get = get_opt,
            set = set_opt,
            min = 4,
            max = 20,
            step = 1,
            bigStep = 1,
            isPercent = false,
            order = 3,
         },
         color = {
            type = 'color',
            name = L['Color'],
            hasAlpha = false,
            width = 'half',
            get = function(info)
               return unpack(get_opt(info))
            end,
            set = function(info, r, g, b)
               set_opt(info, {r, g, b})
            end,
            disabled = function(info)
               return false
            end,
            order = 4,
         },
         halign = {
            type = 'select',
            name = L['Horizontal align'],
            get = get_opt,
            set = set_opt,
            values = function(info)
               return horizontal_align
            end,
            order = 5,
         },
         valign = {
            type = 'select',
            name = L['Vertical align'],
            get = get_opt,
            set = set_opt,
            values = function(info)
               return vertical_align
            end,
            order = 6,
         },
         padding = {
            type = 'range',
            name = L['Padding'],
            get = get_opt,
            set = set_opt,
            min = 0,
            max = 20,
            step = 1,
            bigStep = 1,
            isPercent = false,
            order = 7,
         },
      }
   }
end

function famBagsOptions:GetTitleOptions(frames, db, refreshLayout, name)
   local function get_opt(info)
      local id = info[#info]
      return db.title[id]
   end
   local function set_opt(info, value)
      local id = info[#info]
      db.title[id] = value
      if frames then
         for _, frame in ipairs(frames) do
            if frame then
               famBags:SetTitleInset(frame, db.title.is_inset, db.title.inset, db.title.text.padding)
            end
         end
      end
      if refreshLayout then
         --famBags.Sections:LayoutBags(self.db.profile.layout.general.sections)
         famBags:LayoutBagsButtons()
      end
   end
   local titleframes = {}
   if frames then
      for _, frame in ipairs(frames) do
         if frame and frame.titleFrame then
            table.insert(titleframes, frame.titleFrame)
         end
      end
   end
   local args = self:GetAppearanceOptions(titleframes, db.title, name)
   args['title'] = {
      name = L['General'],
      type = 'group',
      inline = true,
      args = {
         is_inset = {
            type = 'toggle',
            name = L['Is inset'],
            get = get_opt,
            set = set_opt,
            order = 1,
         },
         inset = {
            type = 'range',
            name = L['Inset'],
            get = get_opt,
            set = set_opt,
            min = 0,
            max = 50,
            step = 1,
            bigStep = 1,
            isPercent = false,
            hidden = function(info)
               return not db.title.is_inset
            end,
            order = 2,
         },
      },
      order = 1,
   }
   args['text'] = self:GetTextOptions(titleframes, 'titleText', db.title.text, refreshLayout, false, true)
   return args
end

function famBagsOptions:GetCategoriesOptions()
   return {
      name = L['Categories'],
      type = 'group',
      args = {
         open_categories_config = {
            type = "execute",
            name = 'famBags: '..L['Categories'],
            func = function()
               famBagsOptions.Categories:ShowCategoriesConfig()
            end,
         }
      },
   }
end

function famBagsOptions:AddOrderOptions(orderdb)
   local order = get_array_len(ORDER_ARGS) + 1
   ORDER_ARGS[orderdb.order..'_order'] = {
      type = 'select',
      dialogControl = 'Dropdown',
      name = ' ',
      get = function(info, key)
         return orderdb.order
      end,
--      set = function(info, key, value)
--         orderdb.order = key
--         famBags:LayoutBagsButtons()
--      end,
      values = function(info)
         return { [orderdb.order] = L[orderdb.order] }
      end,
      disabled = true,
      order = order
   }
   ORDER_ARGS[orderdb.order..'_sorting'] = {
      type = 'select',
      dialogControl = 'Dropdown',
      name = ' ',
      get = function(info, key)
         return orderdb.sorting
      end,
      set = function(info, key, value)
         orderdb.sorting = key
         famBags:LayoutBagsButtons()
      end,
      values = function(info)
         local sortings = {}
         for _, s in ipairs(famBags.Orders[orderdb.order]) do
            sortings[s] = L[s]
         end
         return sortings
      end,
      order = order + 1
   }
   ORDER_ARGS[orderdb.order..'_up'] = {
      type = "execute",
      name = L['Up'],
      width = 'half',
      func = function()
         move_order(orderdb, -1)
         famBags:LayoutBagsButtons()
      end,
      order = order + 2,
   }
   ORDER_ARGS[orderdb.order..'_down'] = {
      type = "execute",
      name = L['Down'],
      width = 'half',
      func = function()
         move_order(orderdb, 1)
         famBags:LayoutBagsButtons()
      end,
      order = order + 3,
   }
   ORDER_ARGS[orderdb.order..'_delete'] = {
      type = 'execute',
      name = L['Delete'],
      width = 'half',
      func = function(info)
         delete_order(orderdb)
         famBags:LayoutBagsButtons()
      end,
      order = order + 4,
   }
   ORDER_ARGS[orderdb.order..'_sep'] = {
      type = 'header',
      name = '',
      order = order + 5,
   }
end

